package mapengine.avatars
{
	import core.manager.battle.BattleCountManager;
	import core.manager.battle.BattleEffectManager;
	import core.manager.battle.BattleManager;
	
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.geom.Point;
	
	import framework.core.ComponentBuilder;
	
	import isoengine.interfaces.IMapObjectData;
	import isoengine.interfaces.IMapSprite;
	import isoengine.world.IsoMapSprite;
	
	import mapengine.building.MapAvatar;
	import mapengine.effects.EffectFactory;
	
	import values.avatar.AvatarCampTypeKey;
	import values.avatar.AvatarRoundState;
	import values.avatar.AvatarTemplateValue;
	import values.avatar.AvatarTemplateValueList;
	import values.avatar.IAvatarValue;
	import values.events.AvatarValueEvent;
	import values.skill.SkillValue;
	
	import view.component.menu.AvatarMenu;
	
	public class AvatarBase extends MapAvatar implements IGameAvatar
	{
		public function AvatarBase(descriptor:Object=null)
		{
			super(descriptor);
		}
		
		protected function get menuReference():Class
		{
			return AvatarMenu;
		}
		
		protected var _isDoingAction:Boolean = false;
		
		public function get isDoingAction():Boolean
		{
			return _isDoingAction;
		}
		
		override public function wait():void
		{
			super.wait();
			_isDoingAction = false;
		}
		
		public function myRound(value:Array=null):void
		{
			avatarValue.aiList = value;
			commandAI();
		}
		
		override public function set objectData(value:IMapObjectData):void {
			
			super.objectData = value;
			avatarValue.addEventListener(AvatarValueEvent.DEAD , onAvatarDead);
		}
		
		private function onAvatarDead(value:Event):void
		{
			BattleManager.battleManager.deleteAvatar(this);
			avatarValue.removeEventListener(AvatarValueEvent.DEAD , onAvatarDead);
			currentAsset.addEventListener("die_complete" , onDeadComplete);
			this.playAnimation("die");
		}
		
		private function onDeadComplete(evt:Event):void
		{
			currentAsset.removeEventListener("die_complete" , onDeadComplete);
			wait();
			isoWorld.removeSprite(this);
		}
		
		private function commandAI():void
		{
			var obj:Object = avatarValue.aiList.shift();
			
			switch(obj.command)
			{
				case "move":
					walkTo(obj.target.x , obj.target.y);
					avatarValue.currentRoundState = AvatarRoundState.ATTACT;
					break;
				case "attack":
					attactTarget = obj.target;
					this.playAnimation("attack");
					currentAsset.addEventListener("attack_end" , onAttactEnd);
					currentAsset.addEventListener("attack_complete" , onAttactComplete);
					break;
				case "use_skill":
					attactTarget = obj.target;
					this.playAnimation("attack");
					currentAsset.addEventListener("attack_complete" , onAttactComplete);
					currentAsset.addEventListener("attack_end" , onSkillEnd);
					break;
				case "use_ultimate":
					attactTarget = obj.target;
					this.playAnimation("attack");
					currentAsset.addEventListener("attack_complete" , onAttactComplete);
					currentAsset.addEventListener("attack_end" , onUltimateEnd);
					break;
				case "standby":
					avatarValue.currentRoundState = AvatarRoundState.FINISHED;
					standbyMp();
					break;
			}
		}
		
		private function skillUse(value:SkillValue):void
		{
			var v:Vector.<IsoMapSprite>;
			if(BattleManager.battleManager.isAuto || avatarValue.isOwen)
			{
				v = isoWorld.getSkillRangeAvatars();
			}
			else
			{
				v = isoWorld.rangeOnType(value.range.key , new Point(attactTarget.avatarValue.x , attactTarget.avatarValue.y) ,
				false , false);
			}
			var vNew:Vector.<IAvatarValue> = new Vector.<IAvatarValue>();
			for each(var av:IsoMapSprite in v)
			{
				if(value.isMyTarget(av as IGameAvatar))
				{
					vNew.push( ( av as IGameAvatar ).avatarValue);
				}
			}
			BattleEffectManager.showSkillEffect(value , this.avatarValue , attactTarget.avatarValue);
			value.useSkill(vNew);
		}
		
		override public function walkTo(dx:int, dy:int):void
		{
			_isDoingAction = true;
			super.walkTo(dx, dy);
		}
		
		
		///////////////////////////////////////////////////////////////////手动战斗////////////////////////////////////////////////////////////////////////////////
		
		public function selectMove():void
		{
			_isDoingAction = true;
			avatarValue.tempX = avatarValue.x;
			avatarValue.tempY = avatarValue.y;
			isoWorld.rangeOnDistance(new Point(avatarValue.x , avatarValue.y) ,avatarValue.moveCapability , true , true);
			(isoWorld as IEventDispatcher).addEventListener("click" , onMoveClick);
		}
		
		private function onMoveClick(evt:Event):void
		{
			if(isoWorld.mouseIsoPt.x == avatarValue.x && isoWorld.mouseIsoPt.y == avatarValue.y) return;
			if(isoWorld.getSpriteByPt(isoWorld.mouseIsoPt.x , isoWorld.mouseIsoPt.y) != null) return;
			BattleManager.battleManager.currentAvatar = this;
			isoWorld.rangeOff();
			walkTo(isoWorld.mouseIsoPt.x , isoWorld.mouseIsoPt.y);
			(isoWorld as IEventDispatcher).removeEventListener("click" , onMoveClick);
			avatarValue.currentRoundState = AvatarRoundState.ATTACT;
		}
		
		public function cancelMove():void
		{
			BattleManager.battleManager.currentAvatar = null;
			_isDoingAction = false;
			if(avatarValue.currentRoundState == AvatarRoundState.ATTACT)
			{
				setPosition(avatarValue.tempX , avatarValue.tempY);
				avatarValue.currentRoundState = AvatarRoundState.MOVE;
			}
		}
		
		private function standbyMp():void
		{
			if(BattleManager.battleManager.currentRound > 1)
			{
				avatarValue.mp += AvatarTemplateValueList.noAttackMp;
			}
		}
		
		public function selectStandby():void
		{
			wait();
			BattleManager.battleManager.currentAvatar = null;
			avatarValue.currentRoundState = AvatarRoundState.FINISHED;
		}
		
		public function selectAttact():void
		{
			_isDoingAction = true;
			
			isoWorld.rangeOnDistance(new Point(avatarValue.x , avatarValue.y) , int(avatarValue.distance));
			(isoWorld as IEventDispatcher).addEventListener("click" , onAttactClick);
		}
		
		private function onAttactClick(evt:Event):void
		{
			var isoSprite:IMapSprite = isoWorld.getSpriteByPt(isoWorld.mouseIsoPt.x , isoWorld.mouseIsoPt.y);
			if(!(isoSprite is IGameAvatar)) return;
			if((isoSprite as IGameAvatar).avatarValue.party != -1) return;
			
			attactTarget = (isoSprite as IGameAvatar);
			this.playAnimation("attack");
			currentAsset.addEventListener("attack_end" , onAttactEnd);
			currentAsset.addEventListener("attack_complete" , onAttactComplete);
			isoWorld.rangeOff();
			(isoWorld as IEventDispatcher).removeEventListener("click" , onAttactClick);
		}
		
		private var attactTarget:IGameAvatar;
		
		private function onAttactEnd(evt:Event):void
		{
			currentAsset.removeEventListener("attack_end" , onAttactEnd);
			var obj:* = BattleCountManager.countNormalDamage(avatarValue , attactTarget.avatarValue);
			BattleEffectManager.showDamageEffect(avatarValue , attactTarget.avatarValue , obj);
			countMp(obj , attactTarget);
			attactTarget.hit();
			attactTarget.avatarValue.hp -= obj.data;
			attactTarget = null;
		}
		
		private function countMp(value:Object , hitter:IGameAvatar):void
		{
			var ownerMp:int = AvatarTemplateValueList.hitMp;
			var hitterMp:int = ownerMp;
			
			for each(var str:String in value.state)
			{
				if(str == "dodge")
				{
					hitterMp += AvatarTemplateValueList.dodgeMp;
				} else if(str == "crit")
				{
					ownerMp += AvatarTemplateValueList.critMp;
				} else if(str == "block")
				{
					ownerMp += AvatarTemplateValueList.beBlockedMp;
					hitterMp += AvatarTemplateValueList.blockMp;
				}
			}
			
			avatarValue.mp += ownerMp;
			hitter.avatarValue.mp += hitterMp;
		}
		
		private function onAttactComplete(evt:Event):void
		{
			currentAsset.removeEventListener("attack_complete" , onAttactComplete);
			wait();
			avatarValue.currentRoundState = AvatarRoundState.FINISHED;
			BattleManager.battleManager.currentAvatar = null;
		}
		
		public function selectSkill():void
		{
			_isDoingAction = true;
			isoWorld.rangeOnDistance(new Point(avatarValue.x , avatarValue.y) , int(avatarValue.selectedSkill.distance));
			isoWorld.skillRangeOnType(avatarValue.selectedSkill.range.key);
			(isoWorld as IEventDispatcher).addEventListener("click" , onSkillClicked);
		}
		
		private function onSkillClicked(evt:Event):void
		{
			if(skillClick(avatarValue.selectedSkill))
			{
				currentAsset.addEventListener("attack_end" , onSkillEnd);
			}
		}
		
		private function skillClick(value:SkillValue):Boolean
		{
			var isoSprite:IMapSprite = isoWorld.getSpriteByPt(isoWorld.mouseIsoPt.x , isoWorld.mouseIsoPt.y);
			if(!(isoSprite is IGameAvatar)) return false;
			if(!value.isMyTarget((isoSprite as IGameAvatar) , "target")) return false;
			attactTarget = (isoSprite as IGameAvatar);
			this.playAnimation("attack");
			currentAsset.addEventListener("attack_complete" , onAttactComplete);
			(isoWorld as IEventDispatcher).removeEventListener("click" , onSkillClicked);
			
			return true;
		}
		
		
		
		private function onSkillEnd(evt:Event):void
		{
			currentAsset.removeEventListener("attack_end" , onSkillEnd);
			skillUse(avatarValue.selectedSkill);
			isoWorld.skillRangeOff();
			isoWorld.rangeOff();
		}
		
		public function selectUltimate():void
		{
			_isDoingAction = true;
			isoWorld.rangeOnDistance(new Point(avatarValue.x , avatarValue.y) , int(avatarValue.ultimateSkill.distance));
			isoWorld.skillRangeOnType(avatarValue.ultimateSkill.range.key);
			(isoWorld as IEventDispatcher).addEventListener("click" , ultimateClicked);
		}
		
		private function ultimateClicked(evt:Event):void
		{
			if(skillClick(avatarValue.ultimateSkill))
			{
				currentAsset.addEventListener("attack_end" , onUltimateEnd);
			}
		}
		
		private function onUltimateEnd(evt:Event):void
		{
			currentAsset.removeEventListener("attack_end" , onUltimateEnd);
			skillUse(avatarValue.ultimateSkill);
			isoWorld.skillRangeOff();
			isoWorld.rangeOff();
		}
		
		
		
		override protected function onMoveComplete():void
		{
			super.onMoveComplete();
			
			if(BattleManager.battleManager.isAuto || !avatarValue.isOwen)
			{
				commandAI();
			}
			else
			{
				showMenu(true);
			}
		}
		
		override public function clickFun():void
		{
			
			if (isDoingAction 
				|| (avatarValue.debuff && !avatarValue.debuff.candoThings)
				|| avatarValue.currentRoundState ==  AvatarRoundState.NOT_MY_TURN 
				|| avatarValue.currentRoundState == AvatarRoundState.FINISHED 
				|| BattleManager.battleManager.isAuto || !avatarValue.isOwen
				|| (BattleManager.battleManager.currentAvatar != null && BattleManager.battleManager.currentAvatar != this ))
				return;
			
			showMenu();
		}
		
		protected function showMenu(value:Boolean = false):void
		{
			var menu:AvatarMenu = ComponentBuilder.create(menuReference);
			menu.avatar = this;
			menu.needToStay = value;
			
			EffectFactory.createEffect(menu , avatarValue.x , avatarValue.y , isoWorld);
		}
		
		public function hit():void
		{
			this.playAnimation("hurt");
			currentAsset.addEventListener("hurt_complete" , onHurtComplete);
		}
		
		private function onHurtComplete(evt:Event):void
		{
			wait();
			currentAsset.removeEventListener("hurt_complete" , onHurtComplete);
		}
		
		public function isDead():Boolean
		{
			return avatarValue.isDead;
		}
		
		override public function dispose():void
		{
			avatarValue.removeEventListener(AvatarValueEvent.DEAD , onAvatarDead);
			super.dispose();			
		}
	}
}